use std::fs;
use libc::exit;
use toml::{Table};
use xdg::BaseDirectories;
use crate::inspect;

pub struct Preset ;


impl Preset{
    
    /// merge 
    /// 将两个toml表合并一个table中
    /// 源代码依靠变量遮蔽+递归 可读性比较差 容易混淆变量
    /// 这里代码将变量区分开  
    /// 入参 user_config ; base_config 
    fn merge(a : &mut Table , b : &Table , max: u8) {
        // 遍历b中的每个键值对 (k, v)
        for (k , v ) in b {
            // 情况1: a中存在键k
            let a_value = if let Some(a_value) = a.get_mut(k) {
                a_value // 获取a中k对应值的可变引用
            } else {
                // 情况2: a中不存在键k，直接插入b中的键值对
                a.insert(k.clone(), v.clone());
                continue; // 跳过后续处理
            };

            // 特殊处理: 遇到"icons"键或递归深度已达限制  以user为准
            if k == "icons" || max <= 1 {
                continue; // 保持a中原有值不变
            }

            // 情况3: 若当前a_value和b都是嵌套的Table，递归合并
            if let Some(a_table) = a_value.as_table_mut() {
                if let Some(b_table) = v.as_table() {
                    Self::merge(a_table, b_table, max-1); // 递归合并子表
                    continue;
                }
            }

            // 情况4: 非Table类型或递归终止，直接用b的值覆盖a的值
            *a_value = v.clone();
        }
    }
    fn  merge_str(user : &str , base: &str) -> String {  // &str -> Table进行合并 -> String返回
        let path = BaseDirectories::new()
            .expect("Unable to determine the basic directory location")
            .get_config_file(user) ; 
        let mut user = fs::read_to_string(path) // 1. 读取文件内容为字符串
            .unwrap_or("".to_string()) // 2. 处理文件不存在的情况
            .parse::<Table>().unwrap() ; // 3. 解析字符串为TOML表格
        
        let base = base.parse::<Table>().unwrap() ;
        Self::merge(&mut user, &base , 2) ; // user参数的优先级更高  从base读取user没有的配置到user中
        // inspect!(user) ;
        user.to_string() 
    }
    
    #[inline] 
    pub fn keymap() -> String {
        /// 如果想让代码更具有迁移性，可以通过条件编译+fs::read_to_string的方式替换include_str!
        Self::merge_str("sparrow/keymap.toml" , include_str!("../../config/keymap.toml")) 
    }
    
    #[inline] 
    pub fn theme() -> String {
        Self::merge_str("sparrow/theme.toml" , include_str!("../../config/theme.toml"))
    }
    
    #[inline] 
    pub fn sparrow() -> String {
        Self::merge_str("sparrow/sparrow.toml" , include_str!("../../config/sparrow.toml")) 
    }
}